﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AgnisDAL;
using EbmtDAL.DataSets;
using TestApplication;
using AgnisEbmtTranslator;

namespace TestApplication
{
    class CGlobalProcess
    {
        AgnisDAL.AGNIS_FORMSDataSet dsAgnisForms = new AGNIS_FORMSDataSet();
        //Patient dataset.
        public DataSet dsEbmtPatientG = new DataSet();
        public CGlobalProcess()
        {
        }
        private string statusForm = "";

        #region Connection string settings
        private String currentEbmtDbConnectionString;
        private String currentMappingInfoConnectionString;
        private String currentAgnisStagingConnectionString;
        public void SetCurrentEbmtDbConnectionString(String cString)
        {
            currentEbmtDbConnectionString = cString;
        }

        public void SetCurrentMappingInfoConnectionString(String cString)
        {
            currentMappingInfoConnectionString = cString;
        }
        public void SetCurrentAgnisStagingConnectionString(string cString)
        {
            currentAgnisStagingConnectionString = cString;
        }
        #endregion

        #region Usefull variables for testing P0
        private string sTask1Result;
        public string sTask2Result;
        private string sTask3Result;
        private string sTask3_1Result = "";
        private string sTask3_2Result;
        #endregion

        #region MAIN Function for P0
        public void process0(int ID, int IDAA, DateTime date_Of_Transplant, DateTime date_Of_Report, DateTime date_Of_Death)
        {
            AgnisDAL.cAgnisDAL.SetConnectionString(currentAgnisStagingConnectionString);
            AgnisDAL.cAgnisDAL.LoadAgnisStagingDb(dsAgnisForms);
            EbmtDAL.EbmtDAL.SetCurrentEbmtDbConnectionString(currentEbmtDbConnectionString);
            List<AgnisFormElement> resultFormList = GetDueFormsForThisPatient(ID, IDAA, date_Of_Transplant, date_Of_Report, date_Of_Death);
            if (resultFormList.Count > 0)
            {
                sTask1Result = "Form List Count : " + resultFormList.Count.ToString();
                //Task 2, For each Form,
                foreach (AgnisFormElement FormInstance in resultFormList)
                {
                    int formId;
                    int formRevisionId;
                    int formPublicId;
                    // check if already generated
                    if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(FormInstance.Visit_Id, ID, IDAA, FormInstance.Form_Num) != null)
                    {
                        sTask2Result = "Result for Task 2 ... \r\n";
                        sTask2Result += "Form was already generated. \r\n";

                        formRevisionId = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(FormInstance.Visit_Id,ID, IDAA, FormInstance.Form_Num).FORM_REVISION_ID;
                        formId = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(FormInstance.Form_Num, FormInstance.Visit_Id, ID, IDAA).FORM_ID;
                        //if (FormInstance.Form_Num == 2400)
                        //{
                        //    formPublicId = 0;
                        //}
                        //else
                        //{
                            formPublicId = (int)dsAgnisForms.FORM.FindByFORM_ID(formId).PUBLIC_ID;
                        //}
                        DataRow generatedFormListRow = dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(FormInstance.Visit_Id,ID, IDAA, FormInstance.Form_Num);

                        DateTime oldDate = GetLastSubmissionDate(generatedFormListRow);
                        DateTime currentDate = DateTime.Today; //GetCurrentEbmModificationDate();
                        //Task 3
                        bool isNewModifDate = CompareModDates(oldDate, currentDate);
                        if (isNewModifDate) //Recent modification date
                        {
                            sTask3Result = "Recent date of modification";
                            CheckStatusForm(formRevisionId); //task 3.2
                        }
                        else // same or old modification date
                        {
                            sTask3Result = "Any new modification";
                            if (!IsAcceptedStatusForm(formRevisionId)) //Task 3.1
                            {
                                //Task 3.1.1
                                ChangeProcessStatus(formId, formRevisionId);
                                SendErrorReport();
                            }
                            else // true
                            {
                                // nothing to do
                            }
                        }
                    }
                    else //call for new generation process or Process 1
                    {
                        //for test : Do not process the Form 2400 yet because not ready for mapping
                        //if (FormInstance.Form_Num != 2400)
                        //{                            
                            sTask2Result = "Result for Task 2 ... \r\n";
                            sTask2Result += "Form was not generated yet. \r\n";
                            sTask2Result += "=> Processing P1 for Form " + FormInstance.Form_Num + "; visit ID " + FormInstance.Visit_Id + "; ID " + ID + "; IDAA " + IDAA;

                            CInitialGenerationProcess oMyNewFormRevision = new CInitialGenerationProcess(ID, IDAA, date_Of_Transplant, FormInstance.Due_Period);
                            oMyNewFormRevision.Form_Number = FormInstance.Form_Num;
                            oMyNewFormRevision.SetCurrentEbmtDbConnectionString(currentEbmtDbConnectionString);
                            oMyNewFormRevision.SetCurrentMappingInfoConnectionString(currentMappingInfoConnectionString);
                            oMyNewFormRevision.SetCurrentAgnisStagingConnectionString(currentAgnisStagingConnectionString);
                            oMyNewFormRevision.GenerateNewFormRevision();
                        //}

                    }
                    //MessageBox.Show(sTask1Result + "\r\n" + sTask2Result + "\r\n" + sTask3Result + "\r\n" + sTask3_1Result + "\r\n" + sTask3_2Result);
                }
            }
        }
        #endregion

        #region Primary Functions for P0
        // enum AgnisFormsList { F2400, F2450A, F2450B, F2450C, F2900A, F2900B }
        /// <summary>
        /// TASK 1 - Check "Forms due rules" for each forms 
        /// /// IF (transplant is « allogeneic »)
        /// OR 
        /// (transplant is « autologous » 
        /// AND « patient consents to participate in research »)
        /// </summary>
        /// <param name="ebmt_Id"></param>
        /// <param name="ebmt_Idaa"></param>
        /// <param name="date_Of_Transplant"></param>
        /// <param name="date_Of_Report"></param>
        /// <param name="date_Of_Death"></param>
        /// <returns></returns>
        private List<AgnisFormElement> GetDueFormsForThisPatient(int ebmt_Id, int ebmt_Idaa, DateTime date_Of_Transplant, DateTime date_Of_Report, DateTime date_Of_Death)
        {         
            List<AgnisFormElement> myResultList = new List<AgnisFormElement>();
            AgnisFormElement myForm;
            int form_rev_Id;
            //For Form 2400 
            /* IF Today date is after or equal [Date of HSCT – 14 days] */
            if (date_Of_Report >= date_Of_Transplant.AddDays(-14))
            {
                myForm = new AgnisFormElement(2400, -2, "", TranslatorProcess.AgnisForm2450DuePeriods.Null);
                myResultList.Add(myForm);

            }
            // For Form 2450
            //Verify if this patient is assigned to TED Track, 
            if (IsPatientOnTedTrack()) //not feasible for the moment
            {
                //For Form 2450-TypeOfPeriod is “100 Days”  
                //IF Today date is after or equal [Date of HSCT + 100 days]
                if (date_Of_Report >= date_Of_Transplant.AddDays(100))
                {
                    //IF corresponding Form 2400 exists in GeneratedFormsList table 
                    if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(-2, ebmt_Id, ebmt_Idaa,2400) != null)
                    {   //Is status « Accepted » ? 
                        form_rev_Id = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(-2, ebmt_Id, ebmt_Idaa, 2400).FORM_REVISION_ID;
                        if (IsAcceptedStatusForm(form_rev_Id))
                        {
                            // THEN the Form 2450 100days is due.  
                            myForm = new AgnisFormElement(2450, -1, "", TranslatorProcess.AgnisForm2450DuePeriods.HundredDays);
                            myResultList.Add(myForm);                            
                        }
                    }
                }
                // For 2450-TypeOfPeriod is “6 Months” :
                // IF Today date is after  or equal [Date of HSCT + 6 months]
                if (date_Of_Report >= date_Of_Transplant.AddMonths(6))
                {
                    //IF corresponding Form 2450,with visit_id -1 exists in GeneratedFormsList table
                    if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(-2, ebmt_Id, ebmt_Idaa, 2400) != null)
                    {   //Is status « Accepted » ? 
                        form_rev_Id = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(-2, ebmt_Id, ebmt_Idaa, 2400).FORM_REVISION_ID;
                        if (IsAcceptedStatusForm(form_rev_Id))
                        {
                            // THEN the Form 2450 6Months is due.  
                            myForm = new AgnisFormElement(2450, 0, "", TranslatorProcess.AgnisForm2450DuePeriods.SixtMonths);
                            myResultList.Add(myForm);
                        }
                    }
                }
                // For 2450-TypeOfPeriod is “Annual” :
                // IF Today date is after  or equal [Date of HSCT + 1 year]
                if (date_Of_Report >= date_Of_Transplant.AddYears(1))
                {
                    //IF corresponding Form 2450 exists in GeneratedFormsList table with visit_id 0 AND status is « Accepted » in FORMS table 
                    if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(-2, ebmt_Id, ebmt_Idaa, 2400) != null)
                    {
                        //Is status « Accepted » ? 
                        form_rev_Id = (int)dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(-2, ebmt_Id, ebmt_Idaa, 2400).FORM_REVISION_ID;
                        if (IsAcceptedStatusForm(form_rev_Id))
                        {
                            // THEN the Form 2450 Annual is due.  
                            myForm = new AgnisFormElement(2450, 1, "", TranslatorProcess.AgnisForm2450DuePeriods.Annual);
                            myResultList.Add(myForm);
                        }
                    }
                }
            }
            // For Form 2900
            //	Verify if this patient is assigned to CRF Track, 
            if (IsPatientAssignedToCRFTrack()) //not feasible for the moment                
            {
                //Verify if patient is death
                if (IsPatientDeath(ebmt_Id, ebmt_Idaa, date_Of_Transplant))
                {

                    //	IF Today date is after or equal date of death
                    if (date_Of_Report >= date_Of_Death)
                    {
                        //	IF a previous submitted 2900 exist AND status is “Accepted”
                        //  AND reported that an autopsy was pending to confirm the cause of death
                        if (date_Of_Report >= date_Of_Death.AddMonths(6))
                        {
                            // THEN the Form is due for a confirmatory report.  
                            myForm = new AgnisFormElement(2900, 0, "Confirmatory report", TranslatorProcess.AgnisForm2450DuePeriods.Null);
                            myResultList.Add(myForm);
                        }
                        else
                        {
                            // THEN the Form is due for a first report.  
                            myForm = new AgnisFormElement(2900, -1, "First report", TranslatorProcess.AgnisForm2450DuePeriods.Null);
                            myResultList.Add(myForm);
                        }
                    }
                }
            }
            return myResultList;
        }
        /// <summary>
        /// Check if row exists in GeneratedFormsList table.
        /// Then get the row object
        /// </summary>
        /// <param name="formNum"></param>
        /// <param name="visitId"></param>
        /// <param name="Id"></param>
        /// <param name="Idaa"></param>
        /// <returns></returns>
        private DataRow GetGeneratedFormList(int formNum, int visitId, int Id, int Idaa)
        {
            DataRow myResultDataRow;
            if (dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(visitId, Id, Idaa,formNum) != null)
            {
                myResultDataRow = dsAgnisForms.GENERATED_FORMS_LIST_WITH_STATUS.FindByVISIT_IDIDIDAAFORM_NUMBER(visitId, Id, Idaa, formNum);
                return myResultDataRow;
            }
            else
            {
                return null;
            }
        }


        /// <summary>        
        /// TASK 3.1- Check if response status is  "Accepted"
        /// used also for TASK 1
        /// </summary>
        /// <returns></returns>        
        private Boolean IsAcceptedStatusForm(int form_Revision_Id)
        {
            CheckStatusForm(form_Revision_Id);
            if (statusForm == "ACCEPTED")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// TASK 3.2 Check the response status value
        /// </summary>
        private void CheckStatusForm(int form_Revision_Id)
        {
            statusForm = dsAgnisForms.FORM_REVISION.FindByFORM_REVISION_ID(form_Revision_Id).STATUS;
            switch (statusForm)
            {
                case "ACCEPTED": //Do the process 1 for initial generation
                    sTask3_2Result = "'ACCEPTED' status ";
                    break;
                case "ACCEPTED WITH ERROR": // Do the process 2 for an update
                    sTask3_2Result = "'ACCEPTED with error' status ";
                    break;
                case "REJECTED": // Do the process 2 for an update on modified values
                    sTask3_2Result = "'REJECTED' status ";
                    break;
                default: break;
            }
        }


        /// <summary>
        /// TASK 3 Compare two date values.
        /// </summary>
        /// <param name="LastModDateForFormInAgnisDb">This is the last modification  of the corresponding Form in AGNIS FORM Database, this date is in GeneratedFormsList table </param>
        /// <param name="lastModDateForFormToGenerate">This is the last modification of the corresponding Form we want to generate, issued from comparaison of multiple tables</param>
        /// <returns> TRUE if lastModDateForFormToGenerate > LastModDateForFormInAgnisDb</returns>
        /// <returns> FALSE for all other cases</returns>
        private bool CompareModDates(DateTime LastModDateForFormInAgnisDb, DateTime lastModDateForFormToGenerate)
        {
            return true;
        }
        /// <summary>
        /// TASK 3.1.1.1.1 - send an error report and flag in GeneratedFormsList
        /// </summary>
        private void SendErrorReport()
        {
            //if error Report not sent 
            if (!IsErrorReportSent())
            {
                sTask3Result += " just sending an Error report and flag";
                //then send it AND flag
            }
        }
        /// <summary>
        /// Task 3.1.1.1 - Verify if error report was  already sent
        /// </summary>
        /// <returns></returns>
        private bool IsErrorReportSent()
        {
            return true;
        }
        /// <summary>
        /// TASK 3.1.1 This function changes the PROCESS_STATUS value to "Not Ready" for corresponding form in INFORMATION_PROCESS table
        /// </summary>
        private void 
            ChangeProcessStatus(int form_Id, int formRevision_Id)
        {
            //change status value in Form_Revision table
        }
        #endregion

        #region Secondary Functions for P0

        #region Forms due rules checking
        private Boolean IsPatientOnTedTrack()
        {
            return true;
            //Not feasible actually
        }
        private Boolean IsPatientAssignedToCRFTrack()
        {
            return true;
            //Not feasible actually
        }
        private Boolean IsPatientDeath(int ebmtPatientID, int ebmtPatientIDAA, DateTime ebmtPatientDateOfTransplant)
        {
            dsEbmtPatientG = EbmtDAL.EbmtDAL.LoadPatientData(ebmtPatientID, ebmtPatientIDAA);

            //does patient exist in assessment table
            DataView dViewAssessment = new DataView(dsEbmtPatientG.Tables["B4"]);
            //dViewAssessment.RowFilter = "IDAABC = #" + ebmtPatientDateOfTransplant.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US")) + "#";
            if (dViewAssessment.Count > 0)
            {
                DataRowView myRowView = (DataRowView)dViewAssessment[dViewAssessment.Count - 1];
                //is Patient alive
                if (myRowView["VPATSTAT"] != System.DBNull.Value)
                {
                    if ((int)myRowView["VPATSTAT"] == 2)
                    {
                        return false;
                    }
                    else
                    {
                        return true;//patient is death
                    }
                }
                else
                {
                    return false;//any information about patient status
                }
            }
            else
            {
                return true;//patient doesn't have any 
            }


        }
        private Boolean Form2900Exist_withAcceptedStatus_AndDeathAutopsyConfirmation(string previous_Form, int ID, int IDAA)
        {
            return true;
        }
        #endregion

        #region Getting dates for Task 3

        private DateTime GetLastSubmissionDate(DataRow dRowForm)
        {
            DateTime ResultDate = Convert.ToDateTime(dRowForm["EBMT_LAST_MOD_TIME"]);
            return ResultDate;
        }
        //private DateTime GetLastEbmtModificationDate(DataRow dRowForm, int formId, int FormRevisionId)
        //{
        //    DateTime ResultLatestDate;
        //    DateTime[] Dates = { dsAgnisForms.FORM.FindByFORM_ID(formId).MODIFICATION_TIME,
        //                           dsAgnisForms.FORM_REVISION.FindByFORM_REVISION_ID(FormRevisionId).MODIFICATION_TIME,
        //                           //dsAgnisForms.MODULE.FindByMODULE_ID(ModuleId).MODIFICATION_TIME
        //                       };
            

        //    return ResultLatestDate;
        //}

        private void GetRowFormModuleTable(int moduleId, int formRevisionId)
        {
            //select * from Module where module = ModuleId and formRevisionId = formRevId and MAX(Modification_date)
        }
        #endregion



        #endregion



    }
}
